/*
Philip Dilse
dilsep
Assignment 3

unit test for treasure map card
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include "dominion.h"
#include "dominion_helpers.h"

int main() {
    int i;
    int startHandCount = 10;
    int maxHand = 100;
    int handCount;
    int deckCount = 10;
    int testNum;
    int maxTest = 10;
    int player = 0;
    int expectedReturn;
    int actualReturn;
    int handPos;
    int randomCard;
    int goldCount, goldCountInSupply;
    int cardCounts[treasure_map + 1];
    struct gameState *gs = newGame();
 
    // set up random number gen
    srand(time(NULL));

    gs->whoseTurn = player;
    for (testNum = 0; testNum < maxTest; testNum++) {
        for (handCount = startHandCount; handCount <= maxHand; handCount++) {
            expectedReturn = 0;
            goldCount = 0;
            goldCountInSupply = 0;

            // initialize card counts
            for (i = 0; i <= treasure_map; i++) {
                cardCounts[i] = 0;
            }
            
            // initialize deck with curses, gained gold should be at the back after
            gs->deckCount[player] = deckCount;
            for (i = 0; i < deckCount; i++) {
                gs->deck[player][i] = curse;
            }
            
            // initialize supply w/ random number of gold from 0 - 5
            goldCountInSupply = rand() % 8;
            gs->supplyCount[gold] = goldCountInSupply;

            // init hand randomly and update cardCounts
            gs->handCount[player] = handCount;
            for (i = 0; i < handCount; i++) {
                randomCard = rand() % (treasure_map + 1);
                gs->hand[player][i] = randomCard;
                cardCounts[randomCard]++;
            }   

            // randomly pick handPos and swap in a treasure_map
            handPos = rand() % handCount;

            // update card count if not swapping treasure_map for a treasure_map
            if (gs->hand[player][handPos] != treasure_map) {
                cardCounts[treasure_map]++;
                cardCounts[gs->hand[player][handPos]]--;
            } 
            gs->hand[player][handPos] = treasure_map;

            if (cardCounts[treasure_map] > 1) {
                expectedReturn = 0;
            } else {
                expectedReturn = -1;
            } 

            actualReturn = cardEffect(treasure_map, 0, 0, 0, gs, handPos, &i);

            if (actualReturn == -1) {
                if (expectedReturn != -1 || cardCounts[treasure_map] != 1)
                    printf("treasure_map() error: handcount=%d expected=%d actual=%d\n", handCount, expectedReturn, actualReturn);
            } else {
                // verify hand count - 2 from original
                if (handCount - 2 != gs->handCount[player])
                    printf("treasure_map() error: bad hand count original=%d new=%d\n", handCount, gs->handCount[player]);

                // verify cardCounts same except for two less treasure_maps
                for (i = 0; i < gs->handCount[player]; i++) {
                    cardCounts[gs->hand[player][i]]--;
                } 
                for (i = 0; i <= treasure_map; i++) {
                    if (i != treasure_map) {
                        if (cardCounts[i] != 0)
                            printf("treasure_map() error: bad cardCount hand=%d card=%d count=%d\n", handCount, i, cardCounts[i]);
                    } else {
                        if (cardCounts[i] != 2)
                            printf("treasure_map() error: bad treasuremap hand=%d card=%d count=%d\n", handCount, i, cardCounts[i]);
                    }
                }

                // verify supply has up to 4 less golds, keep track of how many were taken in goldCount
                if (goldCountInSupply > 3) {
                    goldCount = 4;
                } else {
                    goldCount = goldCountInSupply;
                }

                if (gs->supplyCount[gold] + goldCount != goldCountInSupply) {
                    printf("treasure_map() error: bad supplygold start=%d end=%d count=%d", goldCountInSupply, gs->supplyCount[gold], goldCount);
                    
                }
                // deck count should be old + goldCount
                if (deckCount + goldCount != gs->deckCount[player]) {
                    printf("treasure_map() error: bad deck count old=%d new=%d gold=%d", deckCount, gs->deckCount[player], goldCount);
                }
                // end of deck should have goldCount golds, make sure next is curse
                for (i = gs->deckCount[player] - 1; i > gs->deckCount[player] - goldCount; i--) {
                    if (gs->deck[player][i] != gold) {
                        printf("treasure_map() error: bad gold in deck goldCount=%d\n", goldCount);
                    }
                }
            }
        }
    }
    free(gs);
    return 0;
}
